﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using System.Linq;
using System.Windows.Resources;
using System.Windows;

namespace ViewMaker.Core.Utils
{
    /// <summary>
    /// タイプ処理のユーティリティ
    /// </summary>
    internal static class TypeUtil
    {

        /// <summary>
        /// 指定したタイプの長い形式の名前を取得します（Genericsを[]形式で取得）
        /// </summary>
        /// <param name="type">対象の型</param>
        /// <returns>タイプの名前</returns>
        public static string GetFullTypeString(Type type)
        {
            if (type.IsGenericType)
            {
                string name;
                int offset = type.FullName.IndexOf("`");
                if (offset >= 0)
                {
                    name = type.FullName.Substring(0, offset);
                }
                else
                {
                    name = type.FullName;
                }
                List<string> p = new List<string>();
                foreach (Type paraType in type.GetGenericArguments())
                {
                    p.Add(GetTypeString(paraType));
                }
                return string.Format("{0}<{1}>", name, string.Join(",", p.ToArray()));
            }
            else
            {
                return type.FullName;
            }
        }

        /// <summary>
        /// 指定したタイプの短い形式（名前空間が付かない）の名前を取得します（Genericsを[]形式で取得）
        /// </summary>
        /// <param name="type">対象の型</param>
        /// <returns>タイプの名前</returns>
        public static string GetTypeString(Type type)
        {
            if (type.IsGenericType)
            {
                string name;
                int offset = type.Name.IndexOf("`");
                if (offset >= 0)
                {
                    name = type.Name.Substring(0, offset);
                }
                else
                {
                    name = type.Name;
                }
                List<string> p = new List<string>();
                foreach (Type paraType in type.GetGenericArguments())
                {
                    p.Add(GetTypeString(paraType));
                }
                return string.Format("{0}<{1}>", name, string.Join(",", p.ToArray()));
            }
            else
            {
                return type.Name;
            }
        }

        /// <summary>
        /// Nullableな型かチェックする
        /// </summary>
        /// <param name="type">対象の型</param>
        /// <returns>Nullableの場合はtrue、それ以外はfalse</returns>
        public static bool IsNullable(Type type)
        {
            return (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable<>)));
        }


        /// <summary>
        /// 指定した値をEnum型として取得する。
        /// </summary>
        /// <param name="value">EnumまたはNullable、string型</param>
        /// <param name="targetType">変換するEnum型</param>
        /// <returns></returns>
        public static object GetValueWithEnumParse(object value, Type targetType)
        {
            if (IsNullable(targetType))
            {
                targetType = targetType.GetGenericArguments()[0];
            }

            if (targetType.IsEnum && value is string)
            {
#if !SILVERLIGHT
                return Enum.Parse(targetType, (string)value);
#else
                return Enum.Parse(targetType, (string)value, true);
#endif
            }
            else
            {
                return value;
            }

        }

        /// <summary>
        /// EnumのName一覧を取得する。
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static List<string> GetEnumNames(Type type)
        { 
#if !SILVERLIGHT
            return Enum.GetNames(type).ToList();
#else
            List<string> enumNames = new List<string>();
            foreach (FieldInfo fi in type.GetFields(BindingFlags.Static | BindingFlags.Public))
            {
                enumNames.Add(fi.Name);
            }
            return enumNames; 
#endif
        }
    }
}
